#include <process.h>
#include "./headers/Main.h"

///////////////////////////////////////////////////////////////////////////////////////////////////////////////
PLUGIN_RETURNCODE returncode;

bool sSet_PushToServer = false;
string sSet_pvInterface = "";
string sSet_pvServerNickname = "";
string sSet_pvServerPassword = "";

bool sSet_PushToPublic = false;
string sSet_puInterface = "";
string sSet_puServerNickname = "";
string sSet_puServerPassword = "";

string sSet_ServerPort = "";
wstring wsSet_WelcomeMessage = L"";
bool bSet_Showoutput = false;

EXPORT PLUGIN_RETURNCODE Get_PluginReturnCode()
{
	return returncode;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////
vector<string> vDLLPath;
EXPORT void LoadSettings()
{	
	returncode = DEFAULT_RETURNCODE;

	char szCurDir[MAX_PATH];
	GetCurrentDirectory(sizeof(szCurDir), szCurDir);
	char *szFLConfig = (char*)((char*)GetModuleHandle(0) + 0x25410);
	string scPluginCfgFile = string(szCurDir) + "\\flhook_plugins\\flboard.ini";

	//Loading set and auto config.
	bSet_Showoutput = IniGetB(scPluginCfgFile, "FLServerInfo", "ShowOutputInConsole", false);

	sSet_pvInterface = IniGetS(scPluginCfgFile, "Configure", "ServerInterface", "");
	sSet_pvServerNickname = IniGetS(scPluginCfgFile, "Configure", "ServerNickname", "");
	sSet_pvServerPassword = IniGetS(scPluginCfgFile, "Configure", "ServerPassword", "");
	if (sSet_pvInterface == "" || sSet_pvServerNickname == "" || sSet_pvServerPassword == "")
		sSet_PushToServer = false;
	else 
		sSet_PushToServer = true;

	sSet_puInterface = IniGetS(scPluginCfgFile, "Configure", "PublicServerInterface", "");
	sSet_puServerNickname = IniGetS(scPluginCfgFile, "Configure", "PublicServerName", "");
	sSet_puServerPassword = IniGetS(scPluginCfgFile, "Configure", "PublicServerPassword", "");
	if (sSet_puInterface == "" || sSet_puServerNickname == "" || sSet_puServerPassword == "")
		sSet_PushToPublic = false;
	else 
		sSet_PushToPublic = true;

	sSet_ServerPort = IniGetS(scPluginCfgFile, "FLServerInfo", "ServerPort", "2302");
	wsSet_WelcomeMessage = s2ws(IniGetS(scPluginCfgFile, "FLServerInfo", "WelcomeMessage", ""));
	
	if ((wsSet_WelcomeMessage != L"") && sSet_PushToServer) {
		wsSet_WelcomeMessage += L" ";
		wsSet_WelcomeMessage += s2ws(sSet_pvInterface);
	}
	else if ((wsSet_WelcomeMessage != L"") && sSet_PushToPublic) {
		wsSet_WelcomeMessage += L" ";
		wsSet_WelcomeMessage += s2ws(sSet_puInterface);
	} else
		wsSet_WelcomeMessage = L"";

	// load resource DLLs
	HkLoadDLLConf(szFLConfig);
}

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
	if(fdwReason == DLL_PROCESS_ATTACH)
		LoadSettings();

	return true;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
string FeHandle_UpdatePlayer(wstring wscCharname){ // Use to Update player general info 
	wstring wscUniqueAccID, wscUniqueCharID;
	string scUserData;
	stringstream sData;

	if (wscCharname == L"") return "";

	HkGetAccountDirName(wscCharname, wscUniqueAccID);
	HkGetCharFileName(wscCharname, wscUniqueCharID);

	scUserData = FeProfileDecodec(FeProfilePfPath(wscCharname).c_str());
	if (scUserData != "")
		scUserData = FeProfileParse(scUserData);

	sData << "&p_uaid=" << ws2s(wscUniqueAccID);
	sData << "&p_ucid=" << ws2s(wscUniqueCharID);
	sData << scUserData;

	return sData.str();
}

string FeHandle_UpdateKill(wstring wscKiller, wstring wscVictim, unsigned int iSystemID){ // Use to Update kill info
	stringstream sData;
	sData << FeHandle_UpdatePlayer(wscKiller);
	sData << "&victim=" << ws2s(wscVictim);
	sData << "&system=" << ws2s(GetSystemName(iSystemID));
	sData << "&action=updatekill";
	return sData.str();
}

string FeHandle_UpdateTrade(wstring wscRequester, wstring wscAccepter, unsigned int iSystemID){ // Use to Update trade info
	stringstream sData;
	sData << FeHandle_UpdatePlayer(wscRequester);
	sData << "&accepter=" << ws2s(wscAccepter);
	sData << "&system=" << ws2s(GetSystemName(iSystemID));
	sData << "&action=updatetrade";
	return sData.str();
}

string FeHandle_UpdateSystem(wstring wscCharname, unsigned int iSystemID){ // Use to Update system count
	stringstream sData;
	sData << FeHandle_UpdatePlayer(wscCharname);
	sData << "&system=" << ws2s(GetSystemName(iSystemID));
	sData << "&action=updatesystem";
	return sData.str();
}

string FeHandle_UpdateBase(wstring wscCharname, unsigned int iBaseID){ // Use to Update base count
	stringstream sData;
	sData << FeHandle_UpdatePlayer(wscCharname);
	sData << "&system=" << ws2s(GetBaseName(iBaseID));
	sData << "&action=updatebase";
	return sData.str();
}

string FeHandle_SendComment(wstring wscCharname1, wstring wscCharname2, wstring wscMessage){ // Use to send player comment
	stringstream sData;
	sData << "&reviewer=" << ws2s(wscCharname1);
	sData << "&playername=" << ws2s(wscCharname2);
	sData << "&message=" << ws2s(wscMessage);
	sData << "&action=sendcomment";
	return sData.str();
}

string FeHandle_SendTMsg(wstring wscCharname, wstring wscMessage){ // Use to send shortmessage
	stringstream sData;
	sData << "&playername=" << ws2s(wscCharname);
	sData << "&message=" << ws2s(wscMessage);
	sData << "&action=sendmessage";
	return sData.str();
}

string FeHandle_ReplyTMsg(wstring wscCharname, unsigned int iMsgID, wstring wscMessage){ // Use to reply shortmessage
	stringstream sData;
	sData << "&playername=" << ws2s(wscCharname);
	sData << "&messageID=" << iMsgID;
	sData << "&reply=" << ws2s(wscMessage);
	sData << "&action=replymessage";
	return sData.str();
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////
void FeHandle(LPVOID p){ //Sub thread to process flserver data
	if (sSet_PushToServer && sSet_PushToPublic) {
		if (HANDLETHREADPARAMS *params = reinterpret_cast<HANDLETHREADPARAMS*>(p))
		{
			try {
				stringstream sData, sendData;
				sData << "?&p_pn=" << ws2s(params->wscCharname1);
				sData << "&p_ip=" << ws2s(params->wscIP);

				if (params->Action == HANDLETHREADPARAMS::UPDATEPLAYER) {
					sData << FeHandle_UpdatePlayer(params->wscCharname1);
				} else if (params->Action == HANDLETHREADPARAMS::UPDATEKILL) {
					sData << FeHandle_UpdateKill(params->wscCharname1, params->wscCharname2, params->iID);
				} else if (params->Action == HANDLETHREADPARAMS::UPDATETRADE) {
					sData << FeHandle_UpdateTrade(params->wscCharname1, params->wscCharname2, params->iID);
				} else if (params->Action == HANDLETHREADPARAMS::UPDATESYSTEM) {
					sData << FeHandle_UpdateSystem(params->wscCharname1, params->iID);
				} else if (params->Action == HANDLETHREADPARAMS::UPDATEBASE) {
					sData << FeHandle_UpdateBase(params->wscCharname1, params->iID);
				} else if (params->Action == HANDLETHREADPARAMS::SENDCOMMENT) {
					sData << FeHandle_SendComment(params->wscCharname1, params->wscCharname2, params->Message);
				} else if (params->Action == HANDLETHREADPARAMS::SENDTMSG) {
					sData << FeHandle_SendTMsg(params->wscCharname1, params->Message);
				} else if (params->Action == HANDLETHREADPARAMS::REPLYTMSG) {
					sData << FeHandle_ReplyTMsg(params->wscCharname1, params->iID, params->Message);
				}

				sData << "&s_pt=" << sSet_ServerPort == "" ? "2302" : sSet_ServerPort;
				if (sSet_PushToServer) {
					sendData << sData.str();
					sendData << "&s_n=" << sSet_pvServerNickname;
					sendData << "&s_p=" << sSet_pvServerPassword;

					FeHandle_HttpProcess(sSet_pvInterface, sendData.str());
					sendData.str("");
					sendData.clear();
				}
				if (sSet_PushToPublic) {
					sendData << sData.str();
					sendData << "&s_n=" << sSet_puServerNickname;
					sendData << "&s_p=" << sSet_puServerPassword;

					FeHandle_HttpProcess(sSet_puInterface, sendData.str());
					sendData.str("");
					sendData.clear();
				}
				sData.str("");
				sData.clear();
			}
			catch (...){
				//AddLog("");
			}
		}
	}

	// Try to free the struct
	try {
		delete[] p; // God will help you, and hope you will not crash.
	} 
	catch(...) 
	{
		printf("caught exception\n");
	}
	_endthread();
}

HK_ERROR FeHandle_HttpProcess(string scURL, string scData){
	if (cURL(scURL.c_str(), scData.c_str()) == HKE_OK) {
		return HKE_OK;
	}
	return HKE_UNKNOWN_ERROR;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
EXPORT void SendDeathMsg(wstring wscMsg, uint iSystemID, uint iClientIDVictim, uint iClientIDKiller)
{
	returncode = DEFAULT_RETURNCODE;
	HANDLE hThread;

	HKPLAYERINFO pi1, pi2;
	HANDLETHREADPARAMS *htParams = new HANDLETHREADPARAMS;

	HkGetPlayerInfo(ARG_CLIENTID(iClientIDKiller), pi1, false);
	HkGetPlayerInfo(ARG_CLIENTID(iClientIDVictim), pi2, false);
	
	htParams->wscCharname1 = pi1.wscCharname;
	htParams->wscCharname2 = pi2.wscCharname;
	htParams->wscIP = pi1.wscIP;
	htParams->iID = iSystemID;
	htParams->Action = HANDLETHREADPARAMS::UPDATEKILL;

	hThread = (HANDLE)_beginthread(FeHandle, 0, (LPVOID)htParams);

	return;
}

namespace HkIServerImpl
{    
	EXPORT void __stdcall CharacterSelect(struct CHARACTER_ID const & cId, unsigned int iClientID) {
		try {
			if (wsSet_WelcomeMessage != L"") {
				PrintUserCmdText(iClientID, wsSet_WelcomeMessage);
			}
		} catch (...) {
		
		}
	}

	EXPORT void __stdcall PlayerLaunch(unsigned int iShip, unsigned int iClientID)
	{
		HANDLE hThread;

		HKPLAYERINFO pi;
		HANDLETHREADPARAMS *htParams = new HANDLETHREADPARAMS;

		HkGetPlayerInfo(ARG_CLIENTID(iClientID), pi, false);
		
		htParams->wscCharname1 = pi.wscCharname;
		htParams->wscIP = pi.wscIP;
		htParams->iID = iShip;
		htParams->Action = HANDLETHREADPARAMS::UPDATEPLAYER;

		hThread = (HANDLE)_beginthread(FeHandle, 0, (LPVOID)htParams);

		return;
	}

	EXPORT void __stdcall BaseEnter(unsigned int iBaseID, unsigned int iClientID)
	{
		HANDLE hThread;

		HKPLAYERINFO pi;
		HANDLETHREADPARAMS *htParams = new HANDLETHREADPARAMS;

		HkGetPlayerInfo(ARG_CLIENTID(iClientID), pi, false);
		
		htParams->wscCharname1 = pi.wscCharname;
		htParams->wscIP = pi.wscIP;
		htParams->iID = iBaseID;
		htParams->Action = HANDLETHREADPARAMS::UPDATEBASE;

		hThread = (HANDLE)_beginthread(FeHandle, 0, (LPVOID)htParams);

		return;
	}

	EXPORT void __stdcall JumpInComplete(unsigned int iSystemID, unsigned int iShip) {
		unsigned int iClientID = HkGetClientIDByShip(iShip);
		HANDLE hThread;

		HKPLAYERINFO pi;
		HANDLETHREADPARAMS *htParams = new HANDLETHREADPARAMS;
		HkGetPlayerInfo(ARG_CLIENTID(iClientID), pi, false);
		
		htParams->wscCharname1 = pi.wscCharname;
		htParams->wscIP = pi.wscIP;
		htParams->iID = iSystemID;
		htParams->Action = HANDLETHREADPARAMS::UPDATESYSTEM;

		hThread = (HANDLE)_beginthread(FeHandle, 0, (LPVOID)htParams);

		return;
	}

	EXPORT void __stdcall InitiateTrade(unsigned int iClientID1, unsigned int iClientID2) {
		unsigned int iSystemID;
		HANDLE hThread;

		HKPLAYERINFO pi1, pi2;
		HANDLETHREADPARAMS *htParams = new HANDLETHREADPARAMS;

		pub::Player::GetSystem(iClientID1, iSystemID);
		HkGetPlayerInfo(ARG_CLIENTID(iClientID1), pi1, false);
		HkGetPlayerInfo(ARG_CLIENTID(iClientID2), pi2, false);
		
		htParams->wscCharname1 = pi1.wscCharname;
		htParams->wscCharname2 = pi2.wscCharname;
		htParams->wscIP = pi1.wscIP;
		htParams->iID = iSystemID;
		htParams->Action = HANDLETHREADPARAMS::UPDATETRADE;

		hThread = (HANDLE)_beginthread(FeHandle, 0, (LPVOID)htParams);

		return;
	}
}